package com.ae.shield.common.events;

import com.ae.shield.ModLib;
import com.ae.shield.common.items.ItemIntegratedShield;
import com.ae.shield.common.items.shieldFittings.makers.RubbishShield;
import com.ae.shield.common.items.shieldFittings.makers.ShieldMakerBase;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.DamageSource;
import net.minecraft.util.NonNullList;
import net.minecraftforge.event.entity.living.LivingAttackEvent;
import net.minecraftforge.event.entity.living.LivingDeathEvent;
import net.minecraftforge.event.entity.living.LivingHurtEvent;
import net.minecraftforge.event.entity.living.LivingKnockBackEvent;
import net.minecraftforge.event.entity.player.EntityItemPickupEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;

@Mod.EventBusSubscriber(modid = ModLib.MOD_ID, bus = Mod.EventBusSubscriber.Bus.FORGE)
public class ShieldProtectEvent {
//    @SubscribeEvent
//    public static void onEntityHurt(LivingAttackEvent event) {
//        DamageSource source = event.getSource();
//        float amount = event.getAmount();
//        ItemStack shieldStack = getFirstShield(event.getEntityLiving());
//
//        //用护盾对伤害进行削减
//        if (!shieldStack.isEmpty()) {
//            ItemIntegratedShield shield = (ItemIntegratedShield) shieldStack.getItem();
//            float residue = shield.onEntityHurt(event.getEntityLiving(), shieldStack, amount, source);
//
//            if (residue <= 0f) {
//                event.setAmount(0f);
//                event.setCanceled(true);
//            } else {
//                //若还有剩余伤害则按照原版路线进行伤害计算
//                event.setAmount(residue);
//            }
//        }
//    }

    //当实体受到攻击但还未进行任何伤害计算时触发
    @SubscribeEvent
    public static void onEntityHurt(LivingHurtEvent event) {
        DamageSource source = event.getSource();
        //确保玩家可以被指令或创造模式玩家伤害
        if (source.isCreativePlayer() || source.canHarmInCreative()) {
            return;
        }

        float amount = event.getAmount();
        ItemStack shieldStack = getFirstShield(event.getEntityLiving());

        //用护盾对伤害进行削减
        if (!shieldStack.isEmpty()) {
            ItemIntegratedShield shield = (ItemIntegratedShield) shieldStack.getItem();
            float residue = shield.onEntityHurt(event.getEntityLiving(), shieldStack, amount, source);

            if (residue <= 0f) {
                event.setAmount(0f);
                event.setCanceled(true);
            } else {
                //若还有剩余伤害则按照原版路线进行伤害计算
                event.setAmount(residue);
            }
        }
    }

    /**
     * 当护盾拥有护盾值时为实体添加击退抗性
     */
    @SubscribeEvent
    public static void onKnockBackEvent(LivingKnockBackEvent event) {
        ItemStack shieldStack = getFirstShield(event.getEntityLiving());

        if (!shieldStack.isEmpty()) {
            NonNullList<ItemStack> inv = ItemIntegratedShield.getInventory(shieldStack);

            for (ItemStack maker : inv) {
                Item makerItem = maker.getItem();

                if (maker.isEmpty() || !(makerItem instanceof ShieldMakerBase)) {
                    continue;
                }

                if (((ShieldMakerBase) makerItem).getIntensity(maker) > 0f || ((ShieldMakerBase) makerItem).getPlies(maker) > 0) {
                    event.setCanceled(true);
                }
            }
        }
    }

    @SubscribeEvent
    public static void onEntityDeath(LivingDeathEvent event) {
        if (event.getSource().isCreativePlayer() || event.getSource().canHarmInCreative()) {
            return;
        }

        ItemStack shieldStack = getFirstShield(event.getEntityLiving());
        if (!shieldStack.isEmpty()) {
            ItemIntegratedShield shield = (ItemIntegratedShield) shieldStack.getItem();
            if (shield.onEntityDeath(shieldStack, event.getEntityLiving(), event.getSource())) {
                event.setCanceled(true);
            }
        }
    }

    /**
     * 用于处理垃圾回收护盾的事件
     */
    @SubscribeEvent
    public static void onPlayerPickup(EntityItemPickupEvent event) {
        ItemStack shieldStack = getFirstShield(event.getEntityLiving());

        if (shieldStack.isEmpty()) {
            return;
        }

        ItemStack residue = event.getItem().getItem();

        for (ItemStack itemStack : ItemIntegratedShield.getInventory(shieldStack)) {
            if (itemStack.getItem() instanceof RubbishShield) {
                RubbishShield rubbish = (RubbishShield) itemStack.getItem();
                residue = rubbish.collectRubbish(itemStack, residue);

                if (residue.isEmpty()) {
                    event.getItem().setItem(ItemStack.EMPTY);
                    event.setCanceled(true);
                }
            }
        }
//TODO 可添加是否要保留剩余物品的选项
    }

    /**
     * @return 返回实体携带的所有护盾容器
     */
    public static NonNullList<ItemStack> getShield(LivingEntity livingEntity) {
        NonNullList<ItemStack> shields = NonNullList.create();

        if (livingEntity instanceof PlayerEntity) {
            PlayerEntity player = (PlayerEntity) livingEntity;
            NonNullList<ItemStack> items = player.inventory.mainInventory;
            for (ItemStack stack : items) {
                if (stack.getItem() instanceof ItemIntegratedShield) {
                    shields.add(stack);
                }
            }
        } else {
            ItemStack mainHand = livingEntity.getHeldItemMainhand();
            ItemStack offHand = livingEntity.getHeldItemOffhand();
            if (mainHand.getItem() instanceof ItemIntegratedShield) {
                shields.add(mainHand);
            }
            if (offHand.getItem() instanceof ItemIntegratedShield) {
                shields.add(offHand);
            }
        }

        return shields;
    }

    public static ItemStack getFirstShield(LivingEntity livingEntity) {
        if (livingEntity instanceof PlayerEntity) {
            PlayerEntity player = (PlayerEntity) livingEntity;
            for (ItemStack stack : player.inventory.mainInventory) {
                if (stack.getItem() instanceof ItemIntegratedShield) {
                    return stack;
                }
            }
        } else {
            ItemStack mainHand = livingEntity.getHeldItemMainhand();
            ItemStack offHand = livingEntity.getHeldItemOffhand();
            if (mainHand.getItem() instanceof ItemIntegratedShield) {
                return mainHand;
            }
            if (offHand.getItem() instanceof ItemIntegratedShield) {
                return offHand;
            }
        }
        return ItemStack.EMPTY;
    }
}
